package spider

import (
	"asocrawler/conf"
	"asocrawler/db"
	"asocrawler/tool"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strconv"
	"strings"
	"time"
)

const (
	hostUrl = "https://www.taptap.cn"
	XUA     = "&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D54%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D%26VID%3D%26DT%3DPC"
	// 热门榜
	taptapHotUrl = "https://www.taptap.cn/webapiv2/app-top/v2/hits?platform=android&type_name=hot&dataSource=Android&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D100%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D3e695c27-cd28-4a09-98b0-d0a8ae1e66a0%26DT%3DPC%26OS%3DWindows%26OSV%3D10.0.0"
	// 预约榜
	taptapReserveUrl = "https://www.taptap.cn/webapiv2/app-top/v2/hits?type_name=reserve&dataSource=Android&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D100%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D3e695c27-cd28-4a09-98b0-d0a8ae1e66a0%26DT%3DPC%26OS%3DWindows%26OSV%3D10.0.0"
	// 热卖榜
	taptapSellUrl = "https://www.taptap.cn/webapiv2/app-top/v2/hits?type_name=sell&dataSource=Android&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D100%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D3e695c27-cd28-4a09-98b0-d0a8ae1e66a0%26DT%3DPC%26OS%3DWindows%26OSV%3D10.0.0"
	// 云玩榜
	//taptapCloudGameUrl = "https://www.taptap.com/webapiv2/app-top/v1/hits?type_name=cloud_game&platform=android&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D54%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D%26VID%3D%26DT%3DPC"
	// 热玩榜
	taptapPopUrl = "https://www.taptap.cn/webapiv2/app-top/v2/hits?type_name=pop&dataSource=Android&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D100%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D3e695c27-cd28-4a09-98b0-d0a8ae1e66a0%26DT%3DPC%26OS%3DWindows%26OSV%3D10.0.0"
	// 新品榜
	//taptapNewUrl = "https://www.taptap.com/webapiv2/app-top/v1/hits?type_name=new&platform=android&X-UA=V%3D1%26PN%3DWebApp%26LANG%3Dzh_CN%26VN_CODE%3D54%26VN%3D0.1.0%26LOC%3DCN%26PLT%3DPC%26DS%3DAndroid%26UID%3D%26VID%3D%26DT%3DPC"

	taptapDetailUrl = "https://www.taptap.cn/webapiv2/app/v2/detail-by-id/"

	taptapOriginUrl = "https://www.taptap.com/app/"
)

type TapTapSpider struct {
	ChannelName  string
	TimeInterval int
	Platform     string
	AppIconMap   map[string]int

	Client *http.Client
	Urlx   *url.URL
}

func NewTapTapSpider() (t *TapTapSpider) {
	jar, err := cookiejar.New(nil)
	if err != nil {
		return nil
	}
	t = &TapTapSpider{
		ChannelName:  "taptap",
		TimeInterval: 2 * 60 * 60,
		Platform:     "Android",
		AppIconMap:   make(map[string]int),
		Client: &http.Client{
			Jar: jar,
		},
	}

	err = t.login()
	if err != nil {
		return
	}
	return
}

func (c *TapTapSpider) login() error {
	wd, err := tool.OpenHeadLessWebDriver()
	if err != nil {
		c.Println("创建浏览器对象失败，err= ", err)
		return err
	}
	//关闭一个webDriver会对应关闭一个chrome窗口
	//但是不会导致seleniumServer关闭
	defer func() {
		wd.Quit()             // 关闭浏览器
		tool.PutBrowserPool() // 返回池子
	}()
	if err = wd.Get(hostUrl); err != nil {
		c.Println("打开登陆网站失败!,err=", err)
		return err
	}
	time.Sleep(1 * time.Second)
	// 判断是否打开了网站
	for {
		title, err := wd.Title()
		if err != nil {
			return err
		}

		if strings.Contains(title, "TapTap") {
			break
		}

		time.Sleep(1 * time.Second)
	}
	time.Sleep(1 * time.Second)

	// 登陆成功，保存cookies
	cookies, err := wd.GetCookies()
	if err != nil {
		c.Println("获取cookies失败,err= ", err)
		return err
	}
	var clist []*http.Cookie
	for _, v := range cookies {
		clist = append(clist, &http.Cookie{
			Name:   v.Name,
			Value:  v.Value,
			Path:   v.Path,
			Domain: v.Domain,
		})
	}
	urlX, _ := url.Parse(hostUrl)
	c.Client.Jar.SetCookies(urlX, clist)

	//time.Sleep(10*time.Hour)
	return err
}

func (this TapTapSpider) Run() {
	go func() {
		this.run()
	}()
}
func (this *TapTapSpider) Println(v ...interface{}) {
	var str = fmt.Sprintf("[%s]-[%s]", this.ChannelName, this.Platform)
	if conf.Conf.Debug.Switch {
		str += "-[Debug]"
	}
	log.Println(str, fmt.Sprintln(v...))
}

type TapTapDetail struct {
	Success bool `json:"success"`
	Data    struct {
		Author      string `json:"author"`
		Description struct {
			Text string `json:"text"`
		} `json:"description"`
		Stat struct {
			HitsTotal   int `json:"hits_total"`
			FansCount   int `json:"fans_count"`
			ReviewCount int `json:"review_count"`
		} `json:"stat"`
		Download struct {
			Apk struct {
				VersionName string `json:"version_name"`
			} `json:"apk"`
		} `json:"download"`
	} `json:"data"`
}

// app详情
func (this *TapTapSpider) appDetail(appId int) (p TapTapDetail, err error) {

	tryTimes := 0
	urlStr := taptapDetailUrl + fmt.Sprint(appId) + "?" + XUA

re:

	req, err := http.NewRequest("GET", urlStr, nil)
	if err != nil {
		return
	}

	req.Header.Set("referer", "https://www.taptap.com/app")
	req.Header.Set("Connection", "close")
	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")

	resp, err := this.Client.Do(req)
	if err != nil {
		if tryTimes < 5 {
			this.Println("appDetail 请求失败,重新请求中 err1，appId=", appId, err)
			tryTimes++
			time.Sleep(1 * time.Second)
			goto re
		}
		this.Println("appDetail error:", err)
		return
	}

	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		if tryTimes < 5 {
			this.Println("appDetail 请求失败,重新请求中 err2，appId=", appId, err)
			tryTimes++

			_ = this.login()

			time.Sleep(1 * time.Second)
			goto re
		}
		this.Println("appDetail error:", err)
		return
	}

	err = json.Unmarshal(b, &p)
	if err != nil {
		if tryTimes < 5 {
			this.Println("appDetail 请求失败,重新请求中 err3，appId=", appId, err)
			tryTimes++

			_ = this.login()

			time.Sleep(1 * time.Second)
			goto re
		}
		this.Println("appDetail string(b):", string(b))
		return
	}
	if !p.Success {
		if tryTimes < 5 {
			this.Println("appDetail 请求失败,重新请求中,appId=", appId, string(b))
			tryTimes++
			time.Sleep(1 * time.Second)
			goto re
		}
		err = errors.New("appDetail 多次请求失败,退出")
		return
	}
	return
}

type TapTapResult struct {
	Success bool `json:"success"`
	Data    struct {
		List []struct {
			App struct {
				Id           int    `json:"id"`
				Title        string `json:"title"`
				ReleasedTime int64  `json:"released_time"`
				Icon         struct {
					OriginalUrl string `json:"original_url"`
				} `json:"icon"`
				Stat struct {
					Rating struct {
						Score string `json:"score"`
					} `json:"rating"`
				} `json:"stat"`
				Tags []struct {
					Id    int    `json:"id"`
					Value string `json:"value"`
				} `json:"tags"`
			} `json:"app"`

			//Title        string `json:"title"`
			//Id           int    `json:"id"`
			//Category     string `json:"category"`
			//ReleasedTime int64  `json:"released_time"`
			//Icon         struct {
			//	OriginalUrl string `json:"original_url"`
			//} `json:"icon"`
			//Stat struct {
			//	Rating struct {
			//		Score string `json:"score"`
			//	} `json:"rating"`
			//} `json:"stat"`
			//Tags []struct {
			//	Id    int    `json:"id"`
			//	Value string `json:"value"`
			//} `json:"tags"`
		} `json:"list"`
		NextPage string `json:"next_page"`
		PrevPage string `json:"prev_page"`
		Total    int    `json:"total"`
	} `json:"data"`
}

//// 热门榜
//func (this *TapTapSpider) hot(date string) (rs db.DbDataResult, err error) {
//	tryTimes := 0
//	urlStr := taptapHotUrl
//	vs := []db.ApiData{}
//	vType := "热门榜"
//
//re:
//	//client := &http.Client{}
//	req, err := http.NewRequest("GET", urlStr, nil)
//	if err != nil {
//		return
//	}
//
//	req.Header.Set("referer", "https://www.taptap.com/top/download")
//	req.Header.Set("Connection", "close")
//	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
//
//	resp, err := this.Client.Do(req)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("hot client.Do error,重新请求中")
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	defer resp.Body.Close()
//	b, err := ioutil.ReadAll(resp.Body)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("hot ioutil.ReadAll error,重新请求中", string(b))
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	var p TapTapResult
//	err = json.Unmarshal(b, &p)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("hot json.Unmarshal error,重新请求中", string(b))
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	if !p.Success {
//		if tryTimes < 20 {
//			this.Println("hot 请求失败,重新请求中", string(b))
//			this.Println(urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		err = errors.New("hot 多次请求失败,退出")
//		return
//	}
//	if len(p.Data.List) > 0 {
//		for _, d := range p.Data.List {
//			time.Sleep(1 * time.Second)
//			// 获取app详情
//			p, err := this.appDetail(d.Id)
//			if err != nil {
//				return rs, err
//			}
//
//			var typeNames []string
//			for _, t := range d.Tags {
//				typeNames = append(typeNames, t.Value)
//			}
//			appId := "taptap-" + fmt.Sprint(d.Id)
//			var icon string
//			if this.AppIconMap[appId] == 0 {
//				icon = d.Icon.OriginalUrl
//				this.AppIconMap[appId] = 1
//			}
//			var totalDownloadCount int
//			if p.Data.Stat.HitsTotal > 0 {
//				totalDownloadCount = p.Data.Stat.HitsTotal
//			} else {
//				totalDownloadCount = p.Data.Stat.FansCount
//			}
//			var score64 float64
//			var score string
//			score64, err = strconv.ParseFloat(d.Stat.Rating.Score, 64)
//			if err != nil {
//				score = d.Stat.Rating.Score
//			} else {
//				score = fmt.Sprintf("%0.1f", score64/2)
//			}
//			v := db.ApiData{
//				AppId:              appId,
//				GameDesc:           tool.Html2Text(p.Data.Description.Text),
//				GameName:           d.Title,
//				GameVersion:        p.Data.Download.Apk.VersionName,
//				Icon:               icon,
//				OnSaleDate:         time.Unix(d.ReleasedTime, 0).Format("2006-01-02"),
//				TypeName:           strings.Join(typeNames, ","),
//				DIndex:             len(vs),
//				BRank:              1,
//				Score:              score,
//				Company:            p.Data.Author,
//				TotalDownloadCount: totalDownloadCount,
//				CommentCount:       p.Data.Stat.ReviewCount,
//				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.Id),
//			}
//			vs = append(vs, v)
//		}
//	}
//	if p.Data.NextPage != "" {
//		urlStr = hostUrl + p.Data.NextPage + XUA
//		time.Sleep(1 * time.Second)
//		goto re
//	}
//	rs = db.DbDataResult{
//		Data:        vs,
//		ChannelName: this.ChannelName,
//		Platform:    this.Platform,
//		RankType:    vType,
//		Date:        date,
//	}
//	return
//}
//
//// 预约榜
//func (this *TapTapSpider) reserve(date string) (rs db.DbDataResult, err error) {
//	tryTimes := 0
//	urlStr := taptapReserveUrl
//	vs := []db.ApiData{}
//	vType := "预约榜"
//re:
//	//client := &http.Client{}
//	req, err := http.NewRequest("GET", urlStr, nil)
//	if err != nil {
//		return
//	}
//	req.Header.Set("referer", "https://www.taptap.com/top/download")
//	req.Header.Set("Connection", "close")
//	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
//	resp, err := this.Client.Do(req)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("reserve client.Do error,重新请求中")
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	defer resp.Body.Close()
//	b, err := ioutil.ReadAll(resp.Body)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("reserve ioutil.ReadAll error,重新请求中", string(b))
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	var p TapTapResult
//	err = json.Unmarshal(b, &p)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("reserve json.Unmarshal error,重新请求中", string(b))
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	if !p.Success {
//		if tryTimes < 20 {
//			this.Println("reserve 请求失败,重新请求中", string(b))
//			this.Println(urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		err = errors.New("reserve 多次请求失败,退出")
//		return
//	}
//	if len(p.Data.List) > 0 {
//		for _, d := range p.Data.List {
//			// 获取app详情
//			p, err := this.appDetail(d.Id)
//			if err != nil {
//				return rs, err
//			}
//
//			var typeNames []string
//			var icon string
//			var totalDownloadCount int
//			var score64 float64
//			var score string
//
//			for _, t := range d.Tags {
//				typeNames = append(typeNames, t.Value)
//			}
//
//			appId := "taptap-" + fmt.Sprint(d.Id)
//
//			if this.AppIconMap[appId] == 0 {
//				icon = d.Icon.OriginalUrl
//				this.AppIconMap[appId] = 1
//			}
//
//			if p.Data.Stat.HitsTotal > 0 {
//				totalDownloadCount = p.Data.Stat.HitsTotal
//			} else {
//				totalDownloadCount = p.Data.Stat.FansCount
//			}
//
//			score64, err = strconv.ParseFloat(d.Stat.Rating.Score, 64)
//			if err != nil {
//				score = d.Stat.Rating.Score
//			} else {
//				score = fmt.Sprintf("%0.1f", score64/2)
//			}
//
//			v := db.ApiData{
//				AppId:              appId,
//				GameDesc:           tool.Html2Text(p.Data.Description.Text),
//				GameName:           d.Title,
//				GameVersion:        p.Data.Download.Apk.VersionName,
//				Icon:               icon,
//				OnSaleDate:         time.Unix(d.ReleasedTime, 0).Format("2006-01-02"),
//				TypeName:           strings.Join(typeNames, ","),
//				DIndex:             len(vs),
//				BRank:              1,
//				Score:              score,
//				Company:            p.Data.Author,
//				TotalDownloadCount: totalDownloadCount,
//				CommentCount:       p.Data.Stat.ReviewCount,
//				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.Id),
//			}
//			vs = append(vs, v)
//		}
//	}
//	if p.Data.NextPage != "" {
//		urlStr = hostUrl + p.Data.NextPage + XUA
//		time.Sleep(1 * time.Second)
//		goto re
//	}
//	rs = db.DbDataResult{
//		Data:        vs,
//		ChannelName: this.ChannelName,
//		Platform:    this.Platform,
//		RankType:    vType,
//		Date:        date,
//	}
//	return
//}
//
//// 热卖榜
//func (this *TapTapSpider) sell(date string) (rs db.DbDataResult, err error) {
//	tryTimes := 0
//	urlStr := taptapSellUrl
//	vs := []db.ApiData{}
//	vType := "热卖榜"
//re:
//	//client := &http.Client{}
//	req, err := http.NewRequest("GET", urlStr, nil)
//	if err != nil {
//		return
//	}
//	req.Header.Set("referer", "https://www.taptap.com/top/download")
//	req.Header.Set("Connection", "close")
//	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
//	resp, err := this.Client.Do(req)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("sell client.Do error,重新请求中")
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	defer resp.Body.Close()
//	b, err := ioutil.ReadAll(resp.Body)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("sell ioutil.ReadAll error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	var p TapTapResult
//	err = json.Unmarshal(b, &p)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("sell json.Unmarshal error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	if !p.Success {
//		if tryTimes < 20 {
//			this.Println("sell 请求失败,重新请求中", string(b))
//			this.Println(urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		err = errors.New("sell 多次请求失败,退出")
//		return
//	}
//	if len(p.Data.List) > 0 {
//		for _, d := range p.Data.List {
//			// 获取app详情
//			p, err := this.appDetail(d.Id)
//			if err != nil {
//				return rs, err
//			}
//			var typeNames []string
//			for _, t := range d.Tags {
//				typeNames = append(typeNames, t.Value)
//			}
//			appId := "taptap-" + fmt.Sprint(d.Id)
//			var icon string
//			if this.AppIconMap[appId] == 0 {
//				icon = d.Icon.OriginalUrl
//				this.AppIconMap[appId] = 1
//			}
//			var totalDownloadCount int
//			if p.Data.Stat.HitsTotal > 0 {
//				totalDownloadCount = p.Data.Stat.HitsTotal
//			} else {
//				totalDownloadCount = p.Data.Stat.FansCount
//			}
//			var score64 float64
//			var score string
//			score64, err = strconv.ParseFloat(d.Stat.Rating.Score, 64)
//			if err != nil {
//				score = d.Stat.Rating.Score
//			} else {
//				score = fmt.Sprintf("%0.1f", score64/2)
//			}
//			v := db.ApiData{
//				AppId:              appId,
//				GameDesc:           tool.Html2Text(p.Data.Description.Text),
//				GameName:           d.Title,
//				GameVersion:        p.Data.Download.Apk.VersionName,
//				Icon:               icon,
//				OnSaleDate:         time.Unix(d.ReleasedTime, 0).Format("2006-01-02"),
//				TypeName:           strings.Join(typeNames, ","),
//				DIndex:             len(vs),
//				BRank:              1,
//				Score:              score,
//				Company:            p.Data.Author,
//				TotalDownloadCount: totalDownloadCount,
//				CommentCount:       p.Data.Stat.ReviewCount,
//				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.Id),
//			}
//			vs = append(vs, v)
//		}
//	}
//	if p.Data.NextPage != "" {
//		urlStr = hostUrl + p.Data.NextPage + XUA
//		time.Sleep(1 * time.Second)
//		goto re
//	}
//	rs = db.DbDataResult{
//		Data:        vs,
//		ChannelName: this.ChannelName,
//		Platform:    this.Platform,
//		RankType:    vType,
//		Date:        date,
//	}
//	return
//}
//
//// 云玩榜
//func (this *TapTapSpider) cloudGame(date string) (rs db.DbDataResult, err error) {
//	tryTimes := 0
//	urlStr := taptapCloudGameUrl
//	vs := []db.ApiData{}
//	vType := "云玩榜"
//re:
//	//client := &http.Client{}
//	req, err := http.NewRequest("GET", urlStr, nil)
//	if err != nil {
//		return
//	}
//	req.Header.Set("referer", "https://www.taptap.com/top/download")
//	req.Header.Set("Connection", "close")
//	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
//	resp, err := this.Client.Do(req)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("cloudGame client.Do error,重新请求中")
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	defer resp.Body.Close()
//	b, err := ioutil.ReadAll(resp.Body)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("cloudGame ioutil.ReadAll error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	var p TapTapResult
//	err = json.Unmarshal(b, &p)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("cloudGame json.Unmarshal error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	if !p.Success {
//		if tryTimes < 20 {
//			this.Println("cloudGame 请求失败,重新请求中", string(b))
//			this.Println(urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		err = errors.New("cloudGame 多次请求失败,退出")
//		return
//	}
//	if len(p.Data.List) > 0 {
//		for _, d := range p.Data.List {
//			// 获取app详情
//			p, err := this.appDetail(d.Id)
//			if err != nil {
//				return rs, err
//			}
//			var typeNames []string
//			for _, t := range d.Tags {
//				typeNames = append(typeNames, t.Value)
//			}
//			appId := "taptap-" + fmt.Sprint(d.Id)
//			var icon string
//			if this.AppIconMap[appId] == 0 {
//				icon = d.Icon.OriginalUrl
//				this.AppIconMap[appId] = 1
//			}
//			var totalDownloadCount int
//			if p.Data.Stat.HitsTotal > 0 {
//				totalDownloadCount = p.Data.Stat.HitsTotal
//			} else {
//				totalDownloadCount = p.Data.Stat.FansCount
//			}
//			var score64 float64
//			var score string
//			score64, err = strconv.ParseFloat(d.Stat.Rating.Score, 64)
//			if err != nil {
//				score = d.Stat.Rating.Score
//			} else {
//				score = fmt.Sprintf("%0.1f", score64/2)
//			}
//			v := db.ApiData{
//				AppId:              appId,
//				GameDesc:           tool.Html2Text(p.Data.Description.Text),
//				GameName:           d.Title,
//				GameVersion:        p.Data.Download.Apk.VersionName,
//				Icon:               icon,
//				OnSaleDate:         time.Unix(d.ReleasedTime, 0).Format("2006-01-02"),
//				TypeName:           strings.Join(typeNames, ","),
//				DIndex:             len(vs),
//				BRank:              1,
//				Score:              score,
//				Company:            p.Data.Author,
//				TotalDownloadCount: totalDownloadCount,
//				CommentCount:       p.Data.Stat.ReviewCount,
//				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.Id),
//			}
//			vs = append(vs, v)
//		}
//	}
//	if p.Data.NextPage != "" {
//		urlStr = hostUrl + p.Data.NextPage + XUA
//		time.Sleep(1 * time.Second)
//		goto re
//	}
//	rs = db.DbDataResult{
//		Data:        vs,
//		ChannelName: this.ChannelName,
//		Platform:    this.Platform,
//		RankType:    vType,
//		Date:        date,
//	}
//	return
//}
//
//// 热玩榜
//func (this *TapTapSpider) pop(date string) (rs db.DbDataResult, err error) {
//	tryTimes := 0
//	urlStr := taptapPopUrl
//	vs := []db.ApiData{}
//	vType := "热玩榜"
//re:
//	//client := &http.Client{}
//	req, err := http.NewRequest("GET", urlStr, nil)
//	if err != nil {
//		return
//	}
//	req.Header.Set("referer", "https://www.taptap.com/top/download")
//	req.Header.Set("Connection", "close")
//	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
//	resp, err := this.Client.Do(req)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("pop client.Do error,重新请求中")
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	defer resp.Body.Close()
//	b, err := ioutil.ReadAll(resp.Body)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("pop ioutil.ReadAll error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	var p TapTapResult
//	err = json.Unmarshal(b, &p)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("pop json.Unmarshal error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	if !p.Success {
//		if tryTimes < 20 {
//			this.Println("pop 请求失败,重新请求中", string(b))
//			this.Println(urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		err = errors.New("pop 多次请求失败,退出")
//		return
//	}
//	if len(p.Data.List) > 0 {
//		for _, d := range p.Data.List {
//			// 获取app详情
//			p, err := this.appDetail(d.Id)
//			if err != nil {
//				return rs, err
//			}
//			var typeNames []string
//			for _, t := range d.Tags {
//				typeNames = append(typeNames, t.Value)
//			}
//			appId := "taptap-" + fmt.Sprint(d.Id)
//			var icon string
//			if this.AppIconMap[appId] == 0 {
//				icon = d.Icon.OriginalUrl
//				this.AppIconMap[appId] = 1
//			}
//			var totalDownloadCount int
//			if p.Data.Stat.HitsTotal > 0 {
//				totalDownloadCount = p.Data.Stat.HitsTotal
//			} else {
//				totalDownloadCount = p.Data.Stat.FansCount
//			}
//			var score64 float64
//			var score string
//			score64, err = strconv.ParseFloat(d.Stat.Rating.Score, 64)
//			if err != nil {
//				score = d.Stat.Rating.Score
//			} else {
//				score = fmt.Sprintf("%0.1f", score64/2)
//			}
//			v := db.ApiData{
//				AppId:              appId,
//				GameDesc:           tool.Html2Text(p.Data.Description.Text),
//				GameName:           d.Title,
//				GameVersion:        p.Data.Download.Apk.VersionName,
//				Icon:               icon,
//				OnSaleDate:         time.Unix(d.ReleasedTime, 0).Format("2006-01-02"),
//				TypeName:           strings.Join(typeNames, ","),
//				DIndex:             len(vs),
//				BRank:              1,
//				Score:              score,
//				Company:            p.Data.Author,
//				TotalDownloadCount: totalDownloadCount,
//				CommentCount:       p.Data.Stat.ReviewCount,
//				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.Id),
//			}
//			vs = append(vs, v)
//		}
//	}
//	if p.Data.NextPage != "" {
//		urlStr = hostUrl + p.Data.NextPage + XUA
//		time.Sleep(1 * time.Second)
//		goto re
//	}
//	rs = db.DbDataResult{
//		Data:        vs,
//		ChannelName: this.ChannelName,
//		Platform:    this.Platform,
//		RankType:    vType,
//		Date:        date,
//	}
//	return
//}
//
//// 新品榜
//func (this *TapTapSpider) new(date string) (rs db.DbDataResult, err error) {
//	tryTimes := 0
//	urlStr := taptapNewUrl
//	vs := []db.ApiData{}
//	vType := "新品榜"
//re:
//	//client := &http.Client{}
//	req, err := http.NewRequest("GET", urlStr, nil)
//	if err != nil {
//		return
//	}
//	req.Header.Set("referer", "https://www.taptap.com/top/download")
//	req.Header.Set("Connection", "close")
//	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
//	resp, err := this.Client.Do(req)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("new client.Do error,重新请求中")
//			this.Println("urlStr", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	defer resp.Body.Close()
//	b, err := ioutil.ReadAll(resp.Body)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("new ioutil.ReadAll error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	var p TapTapResult
//	err = json.Unmarshal(b, &p)
//	if err != nil {
//		if tryTimes < 20 {
//			this.Println("new json.Unmarshal error,重新请求中", string(b))
//			this.Println("urlStr：", urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		return
//	}
//	if !p.Success {
//		if tryTimes < 20 {
//			this.Println("new 请求失败,重新请求中", string(b))
//			this.Println(urlStr)
//			tryTimes++
//			time.Sleep(1 * time.Second)
//			goto re
//		}
//		err = errors.New("new 多次请求失败,退出")
//		return
//	}
//	if len(p.Data.List) > 0 {
//		for _, d := range p.Data.List {
//			// 获取app详情
//			p, err := this.appDetail(d.Id)
//			if err != nil {
//				return rs, err
//			}
//			var typeNames []string
//			for _, t := range d.Tags {
//				typeNames = append(typeNames, t.Value)
//			}
//			appId := "taptap-" + fmt.Sprint(d.Id)
//			var icon string
//			if this.AppIconMap[appId] == 0 {
//				icon = d.Icon.OriginalUrl
//				this.AppIconMap[appId] = 1
//			}
//			var totalDownloadCount int
//			if p.Data.Stat.HitsTotal > 0 {
//				totalDownloadCount = p.Data.Stat.HitsTotal
//			} else {
//				totalDownloadCount = p.Data.Stat.FansCount
//			}
//			var score64 float64
//			var score string
//			score64, err = strconv.ParseFloat(d.Stat.Rating.Score, 64)
//			if err != nil {
//				score = d.Stat.Rating.Score
//			} else {
//				score = fmt.Sprintf("%0.1f", score64/2)
//			}
//			v := db.ApiData{
//				AppId:              appId,
//				GameDesc:           tool.Html2Text(p.Data.Description.Text),
//				GameName:           d.Title,
//				GameVersion:        p.Data.Download.Apk.VersionName,
//				Icon:               icon,
//				OnSaleDate:         time.Unix(d.ReleasedTime, 0).Format("2006-01-02"),
//				TypeName:           strings.Join(typeNames, ","),
//				DIndex:             len(vs),
//				BRank:              1,
//				Score:              score,
//				Company:            p.Data.Author,
//				TotalDownloadCount: totalDownloadCount,
//				CommentCount:       p.Data.Stat.ReviewCount,
//				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.Id),
//			}
//			vs = append(vs, v)
//		}
//	}
//	if p.Data.NextPage != "" {
//		urlStr = hostUrl + p.Data.NextPage + XUA
//		time.Sleep(1 * time.Second)
//		goto re
//	}
//	rs = db.DbDataResult{
//		Data:        vs,
//		ChannelName: this.ChannelName,
//		Platform:    this.Platform,
//		RankType:    vType,
//		Date:        date,
//	}
//	return
//}

func (this *TapTapSpider) collectRankData(date, rankType, rankUrl string) (rs db.DbDataResult, err error) {
	tryTimes := 0
	urlStr := rankUrl
	vs := []db.ApiData{}
	vType := rankType
re:
	//client := &http.Client{}
	req, err := http.NewRequest("GET", urlStr, nil)
	if err != nil {
		return
	}

	req.Header.Set("referer", "https://www.taptap.com/top/download")
	req.Header.Set("Connection", "close")
	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")

	resp, err := this.Client.Do(req)
	if err != nil {
		if tryTimes < 20 {
			this.Println("collectRankData client.Do error,重新请求中")
			this.Println("urlStr", urlStr)
			tryTimes++
			time.Sleep(1 * time.Second)
			goto re
		}
		return
	}

	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		if tryTimes < 5 {
			this.Println("collectRankData ioutil.ReadAll error,重新请求中", rankType, rankUrl) //string(b)
			this.Println("urlStr：", urlStr)

			_ = this.login()

			tryTimes++
			time.Sleep(1 * time.Second)
			goto re
		}
		return
	}

	var p TapTapResult

	err = json.Unmarshal(b, &p)
	if err != nil {
		if tryTimes < 5 {
			this.Println("collectRankData json.Unmarshal error,重新请求中", string(b))
			this.Println("urlStr：", urlStr)

			_ = this.login()

			tryTimes++
			time.Sleep(1 * time.Second)
			goto re
		}
		return
	}

	if !p.Success {
		if tryTimes < 5 {
			this.Println("collectRankData 请求失败,重新请求中", string(b))
			this.Println(urlStr)
			tryTimes++
			time.Sleep(1 * time.Second)
			goto re
		}
		err = errors.New("collectRankData 多次请求失败,退出")
		return
	}

	if len(p.Data.List) > 0 {
		for _, d := range p.Data.List {

			time.Sleep(100 * time.Microsecond)

			var appId = "taptap-" + fmt.Sprint(d.App.Id)
			var typeNames []string
			var icon string
			var totalDownloadCount int
			var score64 float64
			var score string

			//获取不到appId就直接跳过
			if d.App.Id == 0 {
				continue
			}

			// 获取app详情
			p, err := this.appDetail(d.App.Id)
			if err != nil {
				return rs, err
			}

			// 标签
			for _, t := range d.App.Tags {
				typeNames = append(typeNames, t.Value)
			}

			// icon是否已经存在
			if this.AppIconMap[appId] == 0 {
				icon = d.App.Icon.OriginalUrl
				this.AppIconMap[appId] = 1
			}

			// 计数
			if p.Data.Stat.HitsTotal > 0 {
				totalDownloadCount = p.Data.Stat.HitsTotal
			} else {
				totalDownloadCount = p.Data.Stat.FansCount
			}

			// 评分
			score64, err = strconv.ParseFloat(d.App.Stat.Rating.Score, 64)
			if err != nil {
				score = d.App.Stat.Rating.Score
			} else {
				score = fmt.Sprintf("%0.1f", score64/2)
			}

			v := db.ApiData{
				AppId:              appId,
				GameDesc:           tool.Html2Text(p.Data.Description.Text),
				GameName:           d.App.Title,
				GameVersion:        p.Data.Download.Apk.VersionName,
				Icon:               icon,
				OnSaleDate:         time.Unix(d.App.ReleasedTime, 0).Format("2006-01-02"),
				TypeName:           strings.Join(typeNames, ","),
				DIndex:             len(vs),
				BRank:              1,
				Score:              score,
				Company:            p.Data.Author,
				TotalDownloadCount: totalDownloadCount,
				CommentCount:       p.Data.Stat.ReviewCount,
				OriginalUrl:        taptapOriginUrl + fmt.Sprint(d.App.Id),
			}
			vs = append(vs, v)
		}
	}

	if p.Data.NextPage != "" {
		urlStr = hostUrl + p.Data.NextPage + XUA
		time.Sleep(1 * time.Second)
		goto re
	}

	rs = db.DbDataResult{
		Data:        vs,
		ChannelName: this.ChannelName,
		Platform:    this.Platform,
		RankType:    vType,
		Date:        date,
	}
	return
}
func (this *TapTapSpider) collect(date string) (bool, error) {

	var err error

	this.AppIconMap, err = db.GetAppIconMap(this.ChannelName, this.Platform)
	if err != nil {
		this.Println("db.GetAppIconMap error,err=", err)
		return false, err
	}

	rankTypeList, err := db.QueryRankTypeList(this.ChannelName, this.Platform)
	if err != nil {
		this.Println("collect QueryRankTypeList err:", err)
		return false, err
	}

	var rankList = map[string]string{
		"热门榜": taptapHotUrl,
		"预约榜": taptapReserveUrl,
		"热卖榜": taptapSellUrl,
		"热玩榜": taptapPopUrl,

		//"新品榜": taptapNewUrl,
		//"云玩榜": taptapCloudGameUrl,
	}

	for rankType, rankUrl := range rankList {
		rs, err := this.collectRankData(date, rankType, rankUrl)
		if err != nil {
			return false, err
		}

		//获取排行榜ID和表后缀
		rs.TablePostfix = rankTypeList[rs.RankType].TablePostfix
		rs.RankTypeId = rankTypeList[rs.RankType].Id

		if len(rs.Data) == 0 {
			this.Println(rankType + " 数据长度为空")
		} else {
			err = db.SaveData(rs)
			if err != nil {
				return false, err
			}
		}

		this.Println(rankType + " 采集完成")
	}

	//rs1, err := this.hot(date)
	//if err != nil {
	//	return false, err
	//}
	//if len(rs1.Data) == 0 {
	//	this.Println("hot 长度为空")
	//} else {
	//	err = db.SaveData(rs1)
	//	if err != nil {
	//		return false, err
	//	}
	//}

	//rs2, err := this.reserve(date)
	//if err != nil {
	//	return false, err
	//}
	//if len(rs2.Data) == 0 {
	//	this.Println("reserve 长度为空")
	//} else {
	//	err = db.SaveData(rs2)
	//	if err != nil {
	//		return false, err
	//	}
	//}
	//this.Println("预约榜采集完成")

	//rs3, err := this.sell(date)
	//if err != nil {
	//	return false, err
	//}
	//if len(rs3.Data) == 0 {
	//	this.Println("sell 长度为空")
	//} else {
	//	err = db.SaveData(rs3)
	//	if err != nil {
	//		return false, err
	//	}
	//}
	//this.Println("热卖榜采集完成")

	//rs4, err := this.cloudGame(date)
	//if err != nil {
	//	return false, err
	//}
	//if len(rs4.Data) == 0 {
	//	this.Println("cloudGame 长度为空")
	//} else {
	//	err = db.SaveData(rs4)
	//	if err != nil {
	//		return false, err
	//	}
	//}
	//this.Println("云玩榜采集完成")

	//rs5, err := this.pop(date)
	//if err != nil {
	//	return false, err
	//}
	//if len(rs5.Data) == 0 {
	//	this.Println("pop 长度为空")
	//} else {
	//	err = db.SaveData(rs5)
	//	if err != nil {
	//		return false, err
	//	}
	//}
	//this.Println("热玩榜采集完成")

	//rs6, err := this.new(date)
	//if err != nil {
	//	return false, err
	//}
	//if len(rs6.Data) == 0 {
	//	this.Println("new 长度为空")
	//} else {
	//	err = db.SaveData(rs6)
	//	if err != nil {
	//		return false, err
	//	}
	//}
	//this.Println("新品榜采集完成")

	return true, nil
}

func (this *TapTapSpider) run() {
	if conf.Conf.Debug.Switch {
		this.Println("taptap 渠道无法采集之前的数据，禁用调试模式！！！")
	} else {
	re:
		fDate := time.Now().Format("2006-01-02")
		this.GetDataByDate(fDate)
		time.Sleep(time.Duration(this.TimeInterval) * time.Second)
		goto re
	}
}

func (this *TapTapSpider) GetDataByDate(date string) {
	this.Println("日期:", date, "开始采集数据...")
	succ, err := this.collect(date)
	if succ {
		this.Println("日期:", date, "采集数据完成 稍后再次采集...")
	} else {
		if err == nil {
			this.Println("日期:", date, "数据未更新 稍后重新采集...")
		} else {
			tool.SendWarn("ASO报警-taptap爬虫报错", "ASO报警-taptap爬虫报错,错误信息："+err.Error())
			this.Println("日期:", date, "出现错误err:", err, "稍后重新采集...")
		}
	}
}
